package com.infoauto.opc.gateway.opc.factory;

import com.infoauto.opc.gateway.model.ThirdInterfaceGroup;
import com.infoauto.opc.gateway.model.ThirdInterfaceNode;
import com.infoauto.opc.gateway.opc.MessageHandler;
import com.infoauto.opc.gateway.opc.model.MqttInterface;
import com.infoauto.opc.gateway.opc.model.MqttInterfaceNode;
import com.infoauto.opc.gateway.opc.model.WebInterface;
import com.infoauto.opc.gateway.opc.model.WebInterfaceNode;
import com.infoauto.opc.gateway.opc.utils.JsonResult;
import com.infoauto.opc.gateway.opc.utils.SpringContextUtils;
import com.infoauto.opc.gateway.service.ThirdInterfaceGroupsService;
import com.infoauto.opc.gateway.service.ThirdInterfaceNodesService;
import org.eclipse.milo.opcua.stack.core.types.builtin.Variant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 第三方接口工厂类
 **/
public class WebInterfaceNodeFactory {
    @Autowired
    private SpringContextUtils springContextUtils;
    // <summary>
    /// Manager实例
    /// </summary>
    private static WebInterfaceNodeFactory _manager;
    /// <summary>
    /// 锁定实例
    /// </summary>
    private static Object oClassLock = new Object();

    /// <summary>
    /// 得到该实例
    /// </summary>
    /// <returns></returns>
    public static WebInterfaceNodeFactory Instance() {
        synchronized (oClassLock) //加锁只生成一个实例
        {
            if (_manager == null) {
                _manager = new WebInterfaceNodeFactory();
            }
        }
        return _manager;
    }
    private final Logger logger = LoggerFactory.getLogger(getClass());
    /// <summary>
    /// 私有的构造函数,防止从外部实例化
    /// </summary>
    private WebInterfaceNodeFactory() {
        mapThirdInterfaces = Collections.synchronizedMap(new HashMap<>());
    }

    /// <summary>
    /// 得到该实例
    /// </summary>
    public static WebInterfaceNodeFactory This() {
        return Instance();
    }

    private Map<String, WebInterface> mapThirdInterfaces;//第三方接口集合

    /**
     * 添加点到对应接口中
     */
    public void addNodeToInterface(String interfaceCode, WebInterfaceNode node) {
        WebInterface oi = this.mapThirdInterfaces.get(interfaceCode);//根据接口代码，获取第三方接口的信息
        if (oi != null) {
            node.setThirdInterface(oi);//第三方配置接口的属性中的第三方接口赋值

            if (oi.getNodes() == null) {
                oi.setNodes(Collections.synchronizedMap(new HashMap<>()));
            }
            oi.getNodes().put(node.getThirdNodeID(), node);//给第三方接口中的接口配置属性赋值
        }
    }


    /**
     * 加载第三方接口
     **/
    public void loadThirdInterfaceGroups() {
        ThirdInterfaceGroupsService uss = springContextUtils.getBean(ThirdInterfaceGroupsService.class);
        List<ThirdInterfaceGroup> groups = uss.select(OpcClientFactory.This().getSiteCode());//查询第三方接口的信息
        for (ThirdInterfaceGroup oig : groups) {
            logger.info("Loading WebInterface InterfaceID = {} InterfaceName = {}",
                    oig.getThirdID(),
                    oig.getThirdInterfaceCode());

            if (!mapThirdInterfaces.containsKey(oig.getThirdInterfaceCode().toUpperCase())) {
                WebInterface intf = new WebInterface();//给第三方接口实体赋值
                intf.setThirdID(oig.getThirdID());//接口ID
                intf.setThirdInterfaceCode(oig.getThirdInterfaceCode().toUpperCase());//接口代码
                intf.setReceiveDataType(oig.getReceiveDataType());//发送接收类型
                intf.setThirdInterfaceName(oig.getThirdInterfaceName());//接口名称
                intf.setCallbackUrl(oig.getCallbackUrl());//回调地址
                intf.setWorkDirection(oig.getWorkDirection());//接口内容
                intf.setDescription(oig.getDescription());//描述
                mapThirdInterfaces.put(oig.getThirdInterfaceCode().toUpperCase(), intf);//赋值给第三方接口集合
            }
        }
    }

    /**
     * 加载第三方接口属性集合
     */
    public void loadThirdInterfaceNodes() {
        ThirdInterfaceNodesService usns = springContextUtils.getBean(ThirdInterfaceNodesService.class);
        List<ThirdInterfaceNode> nodes = usns.select(OpcClientFactory.This().getSiteCode());//查询第三方接口的属性
        for (ThirdInterfaceNode oin : nodes) {
            WebInterfaceNode node = new WebInterfaceNode();//创建第三方配置接口的属性实体并且赋值
            node.setThirdNodeID(oin.getThirdNodeID());//属性ID
            node.setTagLabel(oin.getTagLabel());//属性标签
            node.setTagName(oin.getTagName().toUpperCase());//属性名称
            node.setOpcNodeID(oin.getOpcNodeID());//关联的OPC节点ID
            node.setDataType(oin.getDataType());//数据类型
            node.setThirdInterfaceID(oin.getThirdInterfaceID());//第三方接口ID
            this.addNodeToInterface(oin.getThirdInterfaceCode().toUpperCase(), node);//添加点到对应接口中
            // TODO 第三方接口绑定OPC的关系
            SubscribeNodeFactory.This().matchWebInterfaceNode(node);
        }
    }

    /**
     * 绑定MQ接口属性和第三方接口的属性
     * **/
    public void matchMqttInterfaceNode(MqttInterfaceNode mn) {
            for(WebInterface wi : this.mapThirdInterfaces.values()){
                if(wi.getNodes()!=null) {
                    for (WebInterfaceNode wn : wi.getNodes().values()) {
                        if (mn.getWebInterfaceNode() != null && wn.getThirdNodeID() == mn.getWebInterfaceNode().getThirdNodeID()) {
                            //绑定MQ属性与第三方接口的属性
                            mn.setWebInterfaceNode(wn);

                            //一个第三方接口属性对应多个MQTT接口属性
                            if (wn.getMqttInterfaceNodes() == null) {
                                wn.setMqttInterfaceNodes(Collections.synchronizedMap(new HashMap<>()));
                            }
                            wn.getMqttInterfaceNodes().put(mn.getNodeID(), mn);
                        }
                    }
                }
            }
    }

    /**
     * 根据接口代码，推送数据
     * interfaceName 接口代码
     **/
    public JsonResult publishData(WebInterface wi) {
        boolean flag = false;//推送数据状态标记
        if(wi == null) {
            logger.error("WebInterfaceNodeFactory.publishData() method WebInterface is NULL object");
            //return false; 原版
            return new JsonResult(false,"调用接口失败，method WebInterface is NULL object"); //改造新增
        }
        Map<String,String> map = new HashMap<>();//改造新增写入失败集合
        for (WebInterfaceNode wn : wi.getNodes().values()) {
            Variant v = null;
            if(!wn.getTagValue().equals("null")) {
                switch (wn.getDataType()) {
                    case 0:
                        v = new Variant(new Boolean(wn.getTagValue()));
                        break;
                    case 1:
                        v = new Variant(new Short(wn.getTagValue()));
                        break;
                    case 2:
                        v = new Variant(new Integer(wn.getTagValue()));
                        break;
                    case 3:
                        v = new Variant(new Long(wn.getTagValue()));
                        break;
                    case 4:
                        v = new Variant(new Float(wn.getTagValue()));
                        break;
                    case 5:
                        v = new Variant(new Double(wn.getTagValue()));
                        break;
                    case 6:
                        v = new Variant(new Byte(wn.getTagValue()));
                        break;
                    case 7:
                        v = new Variant(wn.getTagValue());
                        break;
                    case 8:
                        v = new Variant(this.str2BooleanArray(wn.getTagValue()));
                        break;
                    case 9:
                        v = new Variant(this.str2ShortArray(wn.getTagValue()));
                        break;
                    case 10:
                        v = new Variant(this.str2IntegerArray(wn.getTagValue()));
                        break;
                    case 11:
                        v = new Variant(this.str2LongArray(wn.getTagValue()));
                        break;
                    case 12:
                        v = new Variant(this.str2FloatArray(wn.getTagValue()));
                        break;
                    case 13:
                        v = new Variant(this.str2DoubleArray(wn.getTagValue()));
                        break;
                    default:
                        v = new Variant(wn.getTagValue());
                        break;
                }

                //第三方推送到MQ
                if (wn.getMqttInterfaceNodes() != null) {
                    for (MqttInterfaceNode mn : wn.getMqttInterfaceNodes().values()) {
                        mn.setNodeValue(v);
                        MqttInterface mf = mn.getOpcInterface();
                        MessageHandler.This().MqttProcessor(mf.getInterfaceName(), mf.toString());
                        flag = true;
                    }
                }
                // 第三方推送到OPC
                if (wn.getSubscribeNode() != null) {
                    flag = wn.getSubscribeNode().writeNodeValue(v);
                    if(flag!=true){
                        map.put(wn.getSubscribeNode().getNodePath(),v.getValue().toString()); //改造新增
                    }
                }
            }
        }
        if(map!=null && map.size()>0){
            return new JsonResult(false,map.toString());
        }else{
            return new JsonResult(true,"调用成功");//改造新增
        }
        //return flag;原版

    }
    /**
     * 字符串转Boolean数组
     * */
    private Boolean[] str2BooleanArray(String str){
        String[] strArr = str.split(",");
        Boolean[] rst = null;
        if(strArr!=null) {
            rst = new Boolean[strArr.length];
            for(int i = 0; i < rst.length; i++) {
                rst[i] = new Boolean(strArr[i]);
            }
        }
        return rst;
    }

    /**
     * 字符串转Short数组
     * */
    private Short[] str2ShortArray(String str){
        String[] strArr = str.split(",");
        Short[] rst = null;
        if(strArr!=null) {
            rst = new Short[strArr.length];
            for(int i = 0; i < rst.length; i++) {
                rst[i] = new Short(strArr[i]);
            }
        }
        return rst;
    }

    /**
     * 字符串转Integer数组
     * */
    private Integer[] str2IntegerArray(String str){
        String[] strArr = str.split(",");
        Integer[] rst = null;
        if(strArr!=null) {
            rst = new Integer[strArr.length];
            for(int i = 0; i < rst.length; i++) {
                rst[i] = new Integer(strArr[i]);
            }
        }
        return rst;
    }

    /**
     * 字符串转Long数组
     * */
    private Long[] str2LongArray(String str){
        String[] strArr = str.split(",");
        Long[] rst = null;
        if(strArr!=null) {
            rst = new Long[strArr.length];
            for(int i = 0; i < rst.length; i++) {
                rst[i] = new Long(strArr[i]);
            }
        }
        return rst;
    }

    /**
     * 字符串转Float数组
     * */
    private Float[] str2FloatArray(String str){
        String[] strArr = str.split(",");
        Float[] rst = null;
        if(strArr!=null) {
            rst = new Float[strArr.length];
            for(int i = 0; i < rst.length; i++) {
                rst[i] = new Float(strArr[i]);
            }
        }
        return rst;
    }

    /**
     * 字符串转Double数组
     * */
    private Double[] str2DoubleArray(String str){
        String[] strArr = str.split(",");
        Double[] rst = null;
        if(strArr!=null) {
            rst = new Double[strArr.length];
            for(int i = 0; i < rst.length; i++) {
                rst[i] = new Double(strArr[i]);
            }
        }
        return rst;
    }

    /**
     * 读取接口中的值
     * */
    private String readValue(String tagName,Map<Integer,WebInterfaceNode> nodes) {
        String rst = "";
        for(WebInterfaceNode wn : nodes.values()) {
            if (tagName.equals(wn.getTagName())) {
                rst = wn.getTagValue();
                break;
            }
        }
        return  rst;
    }

    /**
     * 根据接口代码获取
     * */
    public WebInterface getWebInterfaceByCode(String interfaceCode){
       WebInterface wi = null;
       if (this.mapThirdInterfaces.containsKey(interfaceCode)) {
           wi = this.mapThirdInterfaces.get(interfaceCode);
       }
       return wi;
    }

    /***
     * 删除节点
     * */
    public void clearNodes(){
        if(this.mapThirdInterfaces!=null){
            this.mapThirdInterfaces.clear();
        }
    }

}
